import os, sys, time, subprocess
import win32con, win32api, win32process

class VimDriver:
    def __init__ (self):
        self.gvim_exe = self.get_gvim_exe()
        self.vim_exe = self.get_vim_exe()
        self.server_name = None
        self.gvim_pid = None
        self._wsh = None

    def get_gvim_exe (self):
        import win32api, win32con
        hkey = win32api.RegOpenKey (win32con.HKEY_LOCAL_MACHINE, r'SOFTWARE\Vim\Gvim')
        return win32api.RegQueryValueEx (hkey, 'path')[0]

    def get_vim_exe (self):
        return os.path.join (os.path.dirname (self.get_gvim_exe()), 'vim.exe')

    def _run_vim (self, *args):
        lst_cmd_line = (self.vim_exe, ) + args
        process = subprocess.Popen (lst_cmd_line, stdout=subprocess.PIPE)
        output = process.communicate ()
        return output [0]

    def _run_gvim (self, *args):
        flags = win32process.NORMAL_PRIORITY_CLASS
        si = win32process.STARTUPINFO()
        cmd_line = '%s %s' % (self.gvim_exe, ' '.join(args))
        tpl_result = win32process.CreateProcess (None, cmd_line, None, None, 0, flags, None, '.', si)
        self.gvim_proc = tpl_result[0]
        self.gvim_pid = tpl_result[2]
        time.sleep (0.5)

    def get_unique_name (self):
        name = time.strftime('%H%M%S')
        if name.upper() in self.get_lst_server():
            raise Exception ('Vim server name: %s already in use' % name)
        return name

    def get_lst_server (self):
        lst_output = self._run_vim ('--serverlist')
        return lst_output.splitlines()

    def run_unique_gvim (self, *args):
        self.server_name = self.get_unique_name ()
        lst_arg = ['--servername', self.server_name] + list(args)
        self._run_gvim (*lst_arg)
        return self.server_name

    def stop (self):
        win32process.TerminateProcess (self.gvim_proc, 0)

    def send_keys (self, text):
        if not self.gvim_pid:
            raise Exception ('No pid for gvim')
        self.wsh.AppActivate (self.gvim_pid)
        time.sleep (0.1)
        self.wsh.SendKeys (text)

    def get_wsh (self):
        if not self._wsh:
            import win32com.client
            self._wsh = win32com.client.Dispatch ('WScript.Shell')
        return self._wsh
    wsh = property (get_wsh)

    def remote_send (self, text):
        self._run_vim ('--servername', self.server_name, '--remote-send', text)

    def remote_expr (self, *args):
        return self._run_vim ('--servername', self.server_name, '--remote-expr', *args)

